home *** CD-ROM | disk | FTP | other *** search
- /* Atari ST async I/O routines, used by "attach asy ..." */
- /* written by Rob Janssen, PE1CHL */
-
- #include <stdio.h>
- #include <time.h>
- #ifndef __TURBOC__
- #include <osbind.h> /* os interface defines */
- # ifdef MWC
- # undef Rsconf
- # define Rsconf(a,b,c,d,e,f) (unsigned long) xbios(15,a,b,c,d,e,f)
- # endif
- #endif
-
- #ifndef Bconmap
- # define Bconmap(dev) (unsigned) xbios(44,dev) /* TT Xbios Bconmap() function */
- #endif
-
- #include "global.h"
- #include "mbuf.h"
- #include "internet.h"
- #include "iface.h"
- #include "asy.h"
- #include "atari.h"
-
- struct asy asy[ASY_MAX];
- unsigned nasy;
-
- /* Interface list header */
- extern struct interface *ifaces;
-
- static int asy_setbuf();
-
- /* Initialize asynch port "dev" */
- int
- asy_init(dev,arg1,arg2,bufsize)
- int16 dev;
- char *arg1,*arg2;
- unsigned bufsize;
- {
- register struct asy *ap;
- unsigned tbufsize;
- unsigned oldmap;
- unsigned long rsconf;
-
- #ifdef DEBUG
- printf("asy_init(%d,%s,%s,%d)\n",dev,arg1,arg2,bufsize); fflush(stdout);
- #endif
- ap = &asy[dev];
- ap->addr = atoi(arg1); /* device number */
- ap->vec = htoi(arg2); /* used for mode flags */
-
- if (ap->addr == 0 || ap->addr == 2) /* backward compatability... */
- ap->addr++; /* (old devs 0,2 are now 1,3) */
-
- if (ap->addr == 4 || ap->addr == 5 || ap->addr > 15) {
- printf("asy%d: Bad address %d\n",dev,ap->addr);
- return -1;
- }
-
- #ifdef DEBUG
- printf("asy_init: ap->addr=%u, ap->vec=%u\n",ap->addr,ap->vec); fflush(stdout);
- #endif
- /* devno's above 5 need Bconmap() to be configured */
-
- if (ap->addr >= MODEM1) {
- if ((oldmap = Bconmap(ap->addr)) >= 44) {
- printf("Warning: cannot configure asy dev %d\n",ap->addr);
- return 0;
- }
- }
-
- /* determine buffering. everybody has receive buffer, but a transmit */
- /* buffer is NOT used for MIDI and RS232-direct */
-
- tbufsize = 0; /* default no tx buffer */
-
- switch (ap->addr)
- {
- case RS232:
- if (ap->vec & 1) /* direct buffer access? */
- goto no_txbuf;
-
- default:
- if ((tbufsize = bufsize) > 1024) /* set tx buffer */
- tbufsize = 1024;
-
- case MIDI:
- no_txbuf:
- if (asy_setbuf(ap,bufsize,tbufsize)) {
- if (ap->addr >= MODEM1)
- Bconmap(oldmap);
-
- return -1;
- }
- break;
- }
-
- if (ap->addr != MIDI) {
- rsconf = Rsconf(-1,-1,-1,-1,-1,-1); /* read present config */
- #ifdef DEBUG
- printf("asy_init: rsconf was %08lx\n",rsconf); fflush(stdout);
- #endif
-
- /* setup for no flow, 8 bits, no parity, leave rest as-is */
-
- Rsconf(-1,0,(int) ((rsconf>>24) & 0x81) | 0x08,-1,(int) (rsconf>>8) & 0x77,-1);
- }
-
- if (ap->addr >= MODEM1)
- Bconmap(oldmap);
-
- return 0;
- }
-
- static int
- asy_setbuf (ap,rbufsize,tbufsize)
- register struct asy *ap;
- unsigned rbufsize,tbufsize;
-
- {
- register struct iorec *ip;
- char *rbufp,*tbufp;
- char i_state;
-
- #ifdef DEBUG
- printf("asy_setbuf: addr=%u rbufsize=%u tbufsize=%u\n",ap->addr,rbufsize,tbufsize); fflush(stdout);
- #endif
- if (ap->addr == MIDI)
- tbufsize = 0; /* MIDI can't have tx buf */
-
- if ((rbufp = malloc(rbufsize)) == NULLCHAR){
- printf("asy %d: No space for rx buffer\n",ap->addr);
- return -1;
- }
-
- if (tbufsize != 0){
- if ((tbufp = malloc(tbufsize)) == NULLCHAR){
- free(rbufp);
- printf("asy %d: No space for tx buffer\n",ap->addr);
- return -1;
- }
- }
-
- ip = (struct iorec *) Iorec((ap->addr == MIDI)? 2 : 0);
-
- ap->in = ip;
- ap->out = ip + 1;
-
- i_state = disable();
-
- /* Save original IOREC values */
- memcpy(&ap->oldin,ap->in,sizeof(struct iorec));
- if (ap->addr != MIDI)
- memcpy(&ap->oldout,ap->out,sizeof(struct iorec));
-
- /* Set up receiver FIFO */
- ap->in->ibuf = rbufp;
- ap->in->ibufsiz = rbufsize;
- ap->in->ibufhd = ap->in->ibuftl = 0;
- ap->in->ibuflow = 0;
- ap->in->ibufhi = rbufsize;
-
- if (tbufsize != 0) {
- /* Set up transmitter FIFO */
- ap->out->ibuf = tbufp;
- ap->out->ibufsiz = tbufsize;
- ap->out->ibufhd = ap->out->ibuftl = 0;
- ap->out->ibuflow = 0;
- ap->out->ibufhi = tbufsize;
- }
-
- restore(i_state);
-
- return 0;
- }
-
- void
- asy_stop(iface)
- struct interface *iface;
- {
- register struct asy *ap;
- char i_state;
-
- #ifdef DEBUG
- printf("asy_stop(0x%lx), dev=%d\n",iface,iface->dev);
- fflush(stdout);
- #endif
-
- ap = &asy[iface->dev];
-
- if (ap->in == NULL) /* no Iorec setup done? */
- return;
-
- if (ap->addr != MIDI)
- while (ap->out->ibufhd != ap->out->ibuftl)
- ; /* wait until all transmitted */
-
- /* Restore old iorecs */
-
- i_state = disable();
-
- free(ap->in->ibuf); /* free the buffer */
- memcpy(ap->in,&ap->oldin,sizeof(struct iorec));
-
- if (ap->addr != MIDI)
- {
- #if 0
- free(ap->out->ibuf); /* transmit buffer too */
- #endif
- memcpy(ap->out,&ap->oldout,sizeof(struct iorec));
- }
-
- restore(i_state);
- }
-
- /* Asynchronous line I/O control */
- asy_ioctl(interface,argc,argv)
- struct interface *interface;
- int argc;
- char *argv[];
- {
- if(argc < 1){
- printf("%d\r\n",asy[interface->dev].speed);
- return 0;
- }
- return asy_speed(interface->dev,atoi(argv[0]));
- }
-
- /* Set asynch line speed */
- int
- asy_speed(dev,speed)
- int dev;
- unsigned int speed;
- {
- register struct asy *ap;
- register int sp;
- unsigned oldmap;
- long sav_ssp;
-
- #ifdef DEBUG
- printf("asy_speed(%d,%u)\n",dev,speed); fflush(stdout);
- #endif
-
- if(speed == 0 || dev >= nasy)
- return -1;
-
- ap = &asy[dev];
-
- switch (ap->addr)
- {
- case MIDI:
- /* midi can run on 500000 or 614400Hz clock (hardware mod) */
- switch (speed)
- {
- case 0x9600: /* = 38400 unsigned... */
- case 31250:
- case 16: /* divide-by-16 */
- sp = 0x95;
- break;
- case 9600:
- case 7812:
- case 64: /* divide-by-64 */
- sp = 0x96;
- break;
- default:
- printf("asy: bad speed on MIDI\n");
- return -1;
- }
-
- sav_ssp = Super(NULL); /* access chip */
- *((char *) 0xfffffc04L) = 0x03; /* RESET it */
- *((char *) 0xfffffc04L) = sp; /* set new program */
- Super(sav_ssp);
- break;
-
- default:
- switch (speed)
- {
- case 19200: sp = 0; break;
- case 9600: sp = 1; break;
- case 4800: sp = 2; break;
- case 2400: sp = 4; break;
- case 1200: sp = 7; break;
- case 600: sp = 8; break;
- case 300: sp = 9; break;
- default:
- if (speed > 32) {
- printf("asy: bad speed on RS232\n");
- return -1;
- }
- sp = speed;
- break;
- }
-
- /* devno's above 5 need Bconmap() to be configured */
-
- if (ap->addr >= MODEM1) {
- if ((oldmap = Bconmap(ap->addr)) >= 44) {
- printf("Warning: cannot set speed for asy dev %d\n",ap->addr);
- return 0;
- }
- }
-
- Rsconf(sp,-1,-1,-1,-1,-1); /* set new speed */
-
- if (ap->addr >= MODEM1)
- Bconmap(oldmap);
-
- break;
- }
-
- ap->speed = speed;
-
- return 0;
- }
-
- /* Send a buffer to serial transmitter */
- asy_output(dev,buf,cnt)
- unsigned dev;
- char *buf;
- unsigned short cnt;
- {
- register struct asy *ap;
- register struct iorec *ip;
- long sav_ssp;
-
- #ifdef XDEBUG
- int i;
- printf("asy_output(%d,0x%lx,%d) data=",dev,buf,cnt);
- for (i = 0; i < cnt; i++)
- printf("%02x ",buf[i] & 0xff);
- printf("\n");
- fflush(stdout);
- #endif
-
- if (dev >= nasy || cnt == 0) /* these "cannot happen" */
- return;
-
- ap = &asy[dev];
-
- switch (ap->addr)
- {
- case MIDI:
- Midiws(cnt - 1,buf); /* write MIDI (unbuffered...) */
- break;
-
- case RS232:
- if (ap->vec & 1) {
- ip = ap->out;
-
- if(ip->ibufhd != ip->ibuftl)
- return; /* Already busy */
-
- /* fake the output record to transmit data */
- ip->ibuf = buf;
- ip->ibufsiz = cnt;
- ip->ibufhd = 0;
- ip->ibuftl = cnt - 1;
- ip->ibuflow = 0;
- ip->ibufhi = cnt + 1;
-
- sav_ssp = Super(NULL); /* supervisor mode to access chip */
-
- /* kick the chip to start interrupts */
- *((char *) (0xfffffa01L+46)) = ip->ibuf[0];
-
- Super(sav_ssp); /* back to user mode */
- break;
- }
-
- default:
- do {
- Bconout(ap->addr,*buf++);
- }
- while (--cnt);
-
- break;
- }
- }
-
- /* Receive characters from asynch line
- * Returns count of characters read
- */
- int16
- asy_recv(dev,buf,cnt)
- int dev;
- register char *buf;
- unsigned cnt;
- {
- unsigned tot;
- register struct asy *ap;
- register struct iorec *ip;
- #ifdef XDEBUG
- int i;
- char *b = buf;
- #endif
-
- ap = &asy[dev];
- tot = 0;
-
- /* Read from serial I/O input buffer */
-
- if (ap->addr == RS232 && (ap->vec & 1)) {
- ip = ap->in;
-
- while (cnt--) {
- if(ip->ibufhd == ip->ibuftl)
- break;
-
- if (++(ip->ibufhd) >= ip->ibufsiz)
- ip->ibufhd = 0;
-
- *buf++ = ip->ibuf[ip->ibufhd];
- tot++;
- }
- } else {
- while (cnt--) {
- if (Bconstat(ap->addr) >= 0)
- break;
-
- *buf++ = Bconin(ap->addr);
- tot++;
- }
- }
-
- #ifdef XDEBUG
- if (tot){
- printf("asy_recv returns %d, data=",tot);
- for (i = 0; i < tot; i++)
- printf("%02x ",b[i] & 0xff);
- printf("\n");
- fflush(stdout);
- }
- #endif
-
- return tot;
- }
-
- int
- stxrdy(dev)
- int dev;
- {
- register struct asy *ap;
-
- if (dev >= nasy)
- return 0;
-
- ap = &asy[dev];
-
- switch (ap->addr)
- {
- case MIDI:
- return 1; /* always ready */
-
- case RS232:
- if (ap->vec & 1)
- return (ap->out->ibufhd == ap->out->ibuftl);
-
- default:
- #ifdef DEBUG
- printf("stxrdy: Bcostat(%d) = %ld\n",ap->addr,Bcostat(ap->addr)); fflush(stdout);
- #endif
- return (Bcostat(ap->addr) != 0);
- }
-
- return 0;
- }
-
-